"""
Case Type   : 故障&可靠性测试
Case Name   : 向普通表插入数据的同时使用tar文件恢复该表
Create At   : 2020/11/23
Owner       : @zou_jialiang0505328126
Description :
    1.创建表，并插入数据,创建索引
    2.使用gs_dump导出该表
    3.对该表插入数据（部分数据重复）
    4. 插入数据的过程中使用gs_restore恢复该表
    5.检查数据一致性
    6.执行tpcc
    7.检查数据一致性
Expect      :
    1.创建表并插入数据成功
    2.导出数据成功
    3.插入成功
    4.恢复成功
    5.数据一致，插入数据成功
    6.执行tpcc成功
    7.数据一致
History     :
    modified: 2021/01/27  modified by @wan005,修改启动tpcc用户
"""

import os
import unittest
import sys
import time
from yat.test import macro
from yat.test import Node

sys.path.append(sys.path[0] + "/../")
from testcase.utils.CommonSH import *
from testcase.utils.Common import Common
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from testcase.utils.ComThread import ComThread


class Basebackup(unittest.TestCase):
    commonshpri = CommonSH('PrimaryDbUser')
    commonshsta = CommonSH('Standby1DbUser')
    commonshsta2 = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info('------------Opengauss_Reliability_Tools_Restore_Case012.py 开始执行------------')
        self.dbPrimaryDbUser = Node(node='PrimaryDbUser')
        self.dbStandby1DbUser = Node(node='Standby1DbUser')
        self.dbStandby2DbUser = Node(node='Standby2DbUser')
        self.db_primary_root_node = Node(node='PrimaryRoot')
        self.Constant = Constant()
        self.common = Common('PrimaryRoot')
        self.restore_file = os.path.join(macro.DB_BACKUP_PATH, 'dump_backup', 'tools_restore_case001.tar')
        self.sql_path = os.path.join(macro.DB_BACKUP_PATH, 'testscript')
        self.tblname = 'restore_case012'
        self.values = '2000000'
        self.idxname = 'restore_case012_idx'

    def test_basebackup(self):
        self.log.info('-------------------创建备份路径-----------------------------------')
        shell_cmd = f'rm -rf {os.path.dirname(self.restore_file)}; mkdir {os.path.dirname(self.restore_file)}'
        self.log.info(shell_cmd)
        result = self.dbPrimaryDbUser.sh(shell_cmd).result()
        self.log.info(result)

        self.log.info('----------------------创建表，插入数据,创建索引------------------------')
        sql = f'create table {self.tblname}(i int); create index {self.idxname} on {self.tblname}(i); \
        insert into {self.tblname} (select * from generate_series(1,{self.values}));'
        result = self.commonshpri.executDbSql(sql)
        self.log.info(result)
        self.assertIn('INSERT', result)

        self.log.info('--------------------导出数据----------------------------')
        result = self.commonshpri.dumpFile(filename=self.restore_file, cmd=f'-F t -t {self.tblname}', get_detail=False)
        self.log.info(result)
        self.assertTrue(result)

        self.log.info('--------------------获取还原前数据库已有表------------------------')
        self.table_list = self.commonshpri.executDbSql(r'\d')
        self.log.info(self.table_list)

        self.log.info('------------------起线程插入数据-----------------------------------')
        start_val = int(self.values) - 400
        end_val = int(self.values) * 2
        insert_thread = ComThread(self.commonshpri.executDbSql, args=(
        f'insert into {self.tblname} (select * from generate_series({str(start_val)},{str(end_val)}));',))
        insert_thread.setDaemon(True)
        insert_thread.start()

        self.log.info('-------------------恢复数据-----------------------------------')
        result = self.commonshpri.restoreFile(self.restore_file)
        self.log.info(result)
        self.assertIn(f'restore operation successful', result)

        self.log.info('-------------------------检查插入数据结果------------------------')
        insert_thread.join(60 * 10)
        result = insert_thread.get_result()
        self.log.info(result)
        self.assertIn('INSERT', result)

        self.log.info('----------------------------对比恢复前后数据是否一致-------------------------')
        time.sleep(5)
        self.table_list_after = self.commonshpri.executDbSql(r'\d')
        self.log.info(self.table_list_after)
        self.assertIn(self.table_list, self.table_list_after)

        self.log.info('-------------------检查主备是否同步-------------------')
        result = self.commonshsta.check_data_consistency()
        self.assertTrue(result)
        result = self.commonshsta2.check_data_consistency()
        self.assertTrue(result)

        self.log.info('--------------------检查数据一致性---------------------')
        nodes_tuple = (self.dbPrimaryDbUser, self.dbStandby1DbUser, self.dbStandby2DbUser)
        flag = self.common.check_data_sample_by_all(r'\d', *nodes_tuple)
        self.assertTrue(flag)

        table_dict = self.common.format_sql_result(self.commonshpri.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f'select count(*) from {name};'
            flag = self.common.check_data_sample_by_all(select_sql, *nodes_tuple)
            self.assertTrue(flag)

        self.log.info('------------------启动TPCC----------------------------')
        result = self.common.startTPCC(
            self.db_primary_root_node, macro.TPCC_PATH)
        self.log.info(result)
        self.assertIn(self.Constant.TPCC_SUCCESS_MSG, result)

        self.log.info('-------------------检查主备是否同步-------------------')
        result = self.commonshsta.check_data_consistency()
        self.assertTrue(result)
        result = self.commonshsta2.check_data_consistency()
        self.assertTrue(result)

        self.log.info('--------------------检查数据一致性---------------------')
        nodes_tuple = (self.dbPrimaryDbUser, self.dbStandby1DbUser, self.dbStandby2DbUser)
        flag = self.common.check_data_sample_by_all(r'\d', *nodes_tuple)
        self.assertTrue(flag)

        table_dict = self.common.format_sql_result(self.commonshpri.executDbSql(r'\d'))
        table_name = table_dict.get('Name')
        for name in table_name:
            select_sql = f'select count(*) from {name};'
            flag = self.common.check_data_sample_by_all(select_sql, *nodes_tuple)
            self.assertTrue(flag)

    def tearDown(self):
        self.log.info('-------------------------环境清理------------------------')
        self.log.info('--------------------------删除备份文件------------------')
        shell_cmd = f'rm -rf {os.path.dirname(self.restore_file)}'
        self.log.info(shell_cmd)
        result = self.dbPrimaryDbUser.sh(shell_cmd).result()
        self.log.info(result)

        self.log.info('----------------------删除执行脚本路径----------------------------')
        shell_cmd = f'rm -rf {self.sql_path}'
        self.log.info(shell_cmd)
        result = self.dbPrimaryDbUser.sh(shell_cmd).result()
        self.log.info(result)

        self.log.info('--------------------------删除表------------------------------')
        result = self.commonshpri.executDbSql(
            f'drop index if exists {self.idxname};drop table if exists {self.tblname};')
        self.log.info(result)

        self.log.info('----------Opengauss_Reliability_Tools_Restore_Case012.py 执行结束-----------------------')
